/*
 * s_smartsensor_manager.c
 *
 *  Created on: 2019��6��19��
 *      Author: hemin
 */
#include "s_smartsensor_manager.h"

#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>
#include <ti/sysbios/knl/Semaphore.h>

#include <ti/sysbios/BIOS.h>
#include <icall.h>
#include "util.h"

#include <icall_ble_api.h>

#include "h_cc2640r2f_define.h"

#include "h_cc2640r2f_gpio.h"
#include "s_ccs811.h"

#include "s_message_handle.h"

#define SmartSensor_QueueEvent              UTIL_QUEUE_EVENT_ID
#define SmartSensor_PERIODEvent             Event_Id_00

#define SmartSensor_ALLEvent                SmartSensor_QueueEvent | \
                                                SmartSensor_PERIODEvent

#define smartsensor_BaseTimeLoopPeriod      500 //ms

#define smartsensor_ccs811loopID            0x0001
#define smartsensor_ccs811loopTime          4 //2000 ms

#define smartsensor_ccs811intevent          0x0001
#define smartsensor_ccs811loopevent         0x0002

#define smartsensor_mpu9250intevent         0x0003

#define s_smartsensor_dbg                   H_CC2640R2F_UART_Debug

typedef struct
{
    unsigned short timeloopID;
    unsigned int timeloopnum;
}timeloopEvt_t;

typedef struct
{
  appEvtHdr_t hdr;  // event header.
  unsigned char *pData;  // event data
} appEvt_t;

//Time loop clock instance
static Clock_Struct timeloopClock;

static timeloopEvt_t smartsensor_ccs811loop;

#define smartsensorTaskMd_Task_Stack_Size   1024//2048
// Task configuration
Task_Handle smartsensor_TaskHandle = NULL;

#if defined __TI_COMPILER_VERSION__
#pragma DATA_ALIGN(smartsensorTaskMd_Task_Stack, 8)
#else
#pragma data_alignment=8
#endif
char smartsensorTaskMd_Task_Stack[smartsensorTaskMd_Task_Stack_Size];

static Event_Handle smartsensor_eventhandle;
static Event_Struct smartsensor_eventstruct;

static Queue_Struct smartsensor_appMsg;
static Queue_Handle smartsensor_appMsgQueue;

static void smartsensor_ccs811intevent_handle(void);


static signed char smartsensor_enqueueAppMsg(unsigned char event, \
                                                    unsigned char state, \
                                                        unsigned char *data)
{
    appEvt_t *pMsg = ICall_malloc(sizeof(appEvt_t));

    // Create dynamic pointer to message.
    if (pMsg)
    {
        pMsg->hdr.event = event;
        pMsg->hdr.state = state;
        pMsg->pData = data;

        // Enqueue the message.
        return Util_enqueueMsg(smartsensor_appMsgQueue, \
                                   smartsensor_eventhandle, \
                                       (unsigned char *)pMsg);
    }

    return (-1);
}

static void smartsensor_processAppMsg(appEvt_t *pMsg)
{
    switch(pMsg->hdr.event)
    {
        case smartsensor_ccs811intevent:
            smartsensor_ccs811intevent_handle();
            break;

        default:
            break;
    }
}


static void smartsensor_timeloopClock_fun(UArg arg)
{
    Event_post(smartsensor_eventhandle, arg);
}

static void smartsensor_gpioinputchangehandle(unsigned char gpio)
{
//    smartsensor_enqueueAppMsg(smartsensor_ccs811intevent, 0, NULL);
    s_smartsensor_dbg("The gpio is %d\r\n", gpio);
}

static void smartsensor_ccs811intevent_handle(void)
{
    s_smartsensor_dbg("Get\r\n");
    s_ccs811_getAlgResultData(&ccs811_t);
    smartsensor_ccs811loop.timeloopnum = smartsensor_ccs811loopTime;

    S_MESSAGE_HANDLE_SingleNotify_RspFromBLE();


    Util_startClock(&timeloopClock);
}

static void smartsensor_timeloopClock_handle(void)
{
    signed char tillstartclock = 0;



    if(smartsensor_ccs811loop.timeloopnum > 0)
    {
        (smartsensor_ccs811loop.timeloopnum)--;
        tillstartclock = 1;
    }
    else
    {
//        s_smartsensor_dbg("Loop Get\r\n");
//        s_ccs811_getnewdata(&ccs811_t);
//        Task_sleep(2000);
//        smartsensor_ccs811loop.timeloopnum = smartsensor_ccs811loopTime;
        smartsensor_enqueueAppMsg(smartsensor_ccs811intevent, 0, NULL);
    }

    if(tillstartclock)
    {
        Util_startClock(&timeloopClock);
    }
}

static void smartsensor_taskmode_taskFxn(UArg a0, UArg a1)
{
    //Registe the event
    Event_Params evParams;
    Event_Params_init(&evParams);
    Event_construct(&smartsensor_eventstruct, &evParams);
    smartsensor_eventhandle = \
                    Event_handle(&smartsensor_eventstruct);

    smartsensor_appMsgQueue = Util_constructQueue(&smartsensor_appMsg);

    H_CC2640R2F_GPIO_InputInit(smartsensor_gpioinputchangehandle);

    Util_constructClock(&timeloopClock, smartsensor_timeloopClock_fun,
                            smartsensor_BaseTimeLoopPeriod, 0, \
                                false, SmartSensor_PERIODEvent);

    smartsensor_ccs811loop.timeloopID = smartsensor_ccs811loopID;
    smartsensor_ccs811loop.timeloopnum = smartsensor_ccs811loopTime;

    Util_startClock(&timeloopClock);
    for(;;)
    {
        unsigned int events;

        events = Event_pend(smartsensor_eventhandle, Event_Id_NONE, SmartSensor_ALLEvent,
                                BIOS_WAIT_FOREVER);

        if(events & SmartSensor_QueueEvent)
        {
            while (!Queue_empty(smartsensor_appMsgQueue))
            {
              appEvt_t *pMsg = (appEvt_t *)Util_dequeueMsg(smartsensor_appMsgQueue);
              if (pMsg)
              {
                // Process message.
                  smartsensor_processAppMsg(pMsg);

                // Free the space from the message.
                ICall_free(pMsg);
              }
            }
        }

        if(events & SmartSensor_PERIODEvent)
        {
            smartsensor_timeloopClock_handle();
        }
    }
}

void smartsensor_TaskMode_createTask(void)
{
    Task_Params taskParams;

    // Configure task
    Task_Params_init(&taskParams);
    taskParams.stack = smartsensorTaskMd_Task_Stack;
    taskParams.stackSize = smartsensorTaskMd_Task_Stack_Size;
    taskParams.priority = 4;
    //Task_construct(&bme680TaskMd_Task, \
                   (Task_FuncPtr)bme680_taskmode_taskFxn, &taskParams, NULL);
    smartsensor_TaskHandle = Task_create((Task_FuncPtr)smartsensor_taskmode_taskFxn, \
                                        &taskParams, NULL);
    if(NULL == smartsensor_TaskHandle)
    {
        s_smartsensor_dbg("smartsensor Task init failed\r\n");
    }
    else
    {
        s_smartsensor_dbg("smartsensor Task init success\r\n");
    }
}
